﻿/*  ----------------------------------------------------------------------------
 *  Author:
 *  Chandra Shekhar Tripathi
 *  ----------------------------------------------------------------------------
 *  Product Name:
 *  DbDocumenter
 *  ----------------------------------------------------------------------------
 *  Year:
 *  2009
 *  ----------------------------------------------------------------------------
 *  File:
 *  UCDatabaseInformation.xaml.cs
 *  ----------------------------------------------------------------------------
 */
namespace DBDocumenter.UserControls
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;

    using DBDocumenter.BLL.Entities;
    using DBDocumenter.BLL.Services;
    using DBDocumenter.BLL.Services.HTML;
    using DBDocumenter.BLL.Services.SQL;
    using DBDocumenter.DAL.SQL;
    using DBDocumenter.Exception;
    using DBDocumenter.Helper;
    using DBDocumenter.Resources;
    using DBDocumenter.RoutedEvents;

    /// <summary>
    /// Interaction logic for UCDatabaseInformation.xaml
    /// </summary>
    public partial class UCDatabaseInformation : UserControl
    {
        #region Fields

        private System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
        private object dummyNode = null;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="UCDatabaseInformation"/> class.
        /// </summary>
        public UCDatabaseInformation()
        {
            InitializeComponent();

            this.backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_DoWork);
            this.backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker_RunWorkerCompleted);
            this.backgroundWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker_ProgressChanged);

            this.backgroundWorker.WorkerSupportsCancellation = true;
            this.backgroundWorker.WorkerReportsProgress = true;
        }

        #endregion Constructors

        #region Delegates

        public delegate void OnSetStatusEventDelegate(string message, int value);

        #endregion Delegates

        #region Events

        public event OnSetStatusEventDelegate SetStatus;

        #endregion Events

        #region Properties

        /// <summary>
        /// Gets or sets the selected image path.
        /// </summary>
        /// <value>The selected image path.</value>
        public string SelectedImagePath
        {
            get; set;
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Sets the user control.
        /// </summary>
        /// <param name="step">The step.</param>
        public void SetUserControl(WizardSteps step)
        {
            grdDBWelcome.Visibility = Visibility.Collapsed;
            grdDBInformation.Visibility = Visibility.Collapsed;
            grdDBComponent.Visibility = Visibility.Collapsed;
            grdDBSummary.Visibility = Visibility.Collapsed;

            if (step.Equals(WizardSteps.Welcome))
            {
                grdDBWelcome.Visibility = Visibility.Visible;
            }
            else if (step.Equals(WizardSteps.DatabaseInformation))
            {
                grdDBInformation.Visibility = Visibility.Visible;
            }
            else if (step.Equals(WizardSteps.DatabaseCompont))
            {
                grdDBComponent.Visibility = Visibility.Visible;
                if (Utility.isServerConnected)
                {
                    grdDBComponent.Opacity = 1;
                    grdDBComponent.IsEnabled = true;
                }
                else
                {
                    grdDBComponent.Opacity = 0.5;
                    grdDBComponent.IsEnabled = false;
                }
            }
            else if (step.Equals(WizardSteps.DatabaseSummary))
            {
                grdDBSummary.Visibility = Visibility.Visible;
                if (Utility.isServerConnected)
                {
                    grdDBSummary.Opacity = 1;
                    grdDBSummary.IsEnabled = true;
                }
                else
                {
                    grdDBSummary.Opacity = 0.5;
                    grdDBSummary.IsEnabled = false;
                }
            }
        }

        /// <summary>
        /// Adds the database.
        /// </summary>
        /// <param name="servers">The servers.</param>
        /// <returns> If information is correct returen true otherwise return false. </returns>
        bool AddDatabase(List<ServerInfo> servers)
        {
            bool result = false;
            try
            {
                cmbDatabase.Items.Clear();
                foreach (ServerInfo server in servers)
                {
                    cmbDatabase.Items.Add(server.DbName);
                }
                if (cmbDatabase.Items.Count > 0)
                {
                    dataBaseStackPanel.Visibility = Visibility.Visible;
                    cmbDatabase.Text = cmbDatabase.Items[0].ToString();
                    result = true;
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Error, ex.Message);
                result = false;
            }
            return result;
        }

        /// <summary>
        /// Handles the Click event of the BtnConnect control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!txtServerName.Text.Equals(string.Empty))
                {
                    Utility.serverName = "Server=" + txtServerName.Text.Trim() + ";";

                    if (chkIntegratedSecurity.IsChecked.Equals(true))
                    {
                        Utility.trustedConnection = "Trusted_Connection=True;";
                    }
                    else
                    {
                        Utility.trustedConnection = "Trusted_Connection=False;";
                    }
                    Utility.userName = "User ID=" + txtUserName.Text + ";";
                    Utility.password = "Password=" + txtPassword.Password + ";";

                    Utility.connectionString = Utility.serverName + Utility.userName + Utility.password + Utility.trustedConnection;
                    UtilityManager.Instance.SetConnectionString(Utility.serverName, Utility.userName, Utility.password, Utility.trustedConnection);

                    List<ServerInfo> servers = SQLDBInfo.Instance.GetDatabases(UtilityManager.Instance.GetConnectionString());

                    if (this.AddDatabase(servers))
                    {
                        SetOpecityAndAccessibility(0.5, false);
                        btnConnect.Visibility = Visibility.Collapsed;
                        btnDisConnect.Visibility = Visibility.Visible;
                        Utility.isServerConnected = true;
                    }
                    else
                    {
                        throw new Exception(PLResources.ServiceNotRunningErrorMessage.Replace("@instanceName", txtServerName.Text));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error loading database-tables into list: " + ex.Message);
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Warn, ex.Message);
                SetDefaultSettings();
            }
            finally
            {

            }
        }

        /// <summary>
        /// Handles the Click event of the BtnDisConnect control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void BtnDisConnect_Click(object sender, RoutedEventArgs e)
        {
            SetOpecityAndAccessibility(1, true);
            btnConnect.Visibility = Visibility.Visible;
            btnDisConnect.Visibility = Visibility.Collapsed;
            cmbDatabase.Items.Clear();
            dataBaseStackPanel.Visibility = Visibility.Hidden;

            Utility.isServerConnected = false;
            Utility.connectionString = string.Empty;
        }

        /// <summary>
        /// Handles the Click event of the BtnGenerate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void BtnGenerate_Click(object sender, RoutedEventArgs e)
        {
            if (Utility.fileLocation.Equals(string.Empty))
            {
                MessageBox.Show(PLResources.Please_select_a_location_to_keep_generated_document, "DBDocumenter", MessageBoxButton.OK, MessageBoxImage.Information);
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Info, PLResources.Please_select_a_location_to_keep_generated_document);
            }
            else
            {
                backgroundWorker.RunWorkerAsync();
            }
        }

        //public bool GetServers()
        //{
        //    SqlDataSourceEnumerator sqldatasourceenumerator1 = SqlDataSourceEnumerator.Instance;
        //    DataTable datatable1 = sqldatasourceenumerator1.GetDataSources();
        //    //cmbServers.DataSource = datatable1;
        //    foreach (DataRow r in datatable1.Rows)
        //    {
        //        string s = r["InstanceName"].ToString();
        //        if (s != "")
        //        {
        //            s = "\\" + s;
        //        }
        //        cmbDatabase.Items.Add(r["ServerName"].ToString() + s);
        //    }
        //    return true;
        //}
        /// <summary>
        /// Sets the default settings.
        /// </summary>
        void SetDefaultSettings()
        {
            txtPassword.Password = string.Empty;
            txtServerName.Text = string.Empty;
            txtUserName.Text = string.Empty;

            chkDatabases.IsChecked = true;
            chkFunctions.IsChecked = true;
            chkStoredProcedure.IsChecked = true;
            chkTables.IsChecked = true;
            chkViews.IsChecked = true;
            chkIntegratedSecurity.IsChecked = false;

            dataBaseStackPanel.Visibility = Visibility.Hidden;
            cmbDatabase.Items.Clear();

            btnConnect.Visibility = Visibility.Visible;
            btnDisConnect.Visibility = Visibility.Collapsed;

            Utility.connectionString = string.Empty;
            Utility.isServerConnected = false;
        }

        /// <summary>
        /// Sets the opecity and accessibility.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
        void SetOpecityAndAccessibility(double value, bool isEnabled)
        {
            lblUserName.Opacity = value;
            lblPassword.Opacity = value;
            lblServer.Opacity = value;
            lblDBInformationHeader.Opacity = value;

            chkIntegratedSecurity.Opacity = value;
            chkIntegratedSecurity.IsEnabled = isEnabled;

            txtServerName.Opacity = value;
            txtServerName.IsEnabled = isEnabled;
            txtPassword.Opacity = value;
            txtPassword.IsEnabled = isEnabled;
            txtUserName.Opacity = value;
            txtUserName.IsEnabled = isEnabled;
        }

        /// <summary>
        /// Handles the Loaded event of the UserControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                foreach (string s in Directory.GetLogicalDrives())
                {
                    TreeViewItem item = new TreeViewItem();
                    item.Header = s;
                    item.Tag = s;
                    item.FontWeight = FontWeights.Normal;
                    item.Items.Add(dummyNode);
                    item.Expanded += new RoutedEventHandler(folder_Expanded);
                    foldersItem.Items.Add(item);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Error, ex.Message);
            }
        }

        /// <summary>
        /// Runs on secondary thread.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        /// <remarks></remarks>
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                string dbName = Utility.databaseName;
                string conString = UtilityManager.Instance.GetConnectionString(dbName);
                
                #region Show Summary Popup

                    this.Dispatcher.BeginInvoke
                        (System.Windows.Threading.DispatcherPriority.Normal, (System.Threading.ThreadStart)delegate()
                        {
                            this.RaiseEvent(
                                new ShowPopUpEventArgs
                                {
                                    RoutedEvent = DBDocumenterEvents.ShowPopUpRoutedEvent,
                                    Value = Visibility.Visible
                                });
                        });

                #endregion

                #region Document Database:- Create databases XML file then convert into htm file
                    
                    backgroundWorker.ReportProgress(0, PLResources.Writing_Databases_information + Environment.NewLine);
                    Utility.databases = SQLDBInfoManager.Instance.GetDatabases(Utility.connectionString);
                    XMLManager.WriteXML(PLResources.Databases_XML_FileName, XMLManager.GetXML(Utility.databases));
                    HTMLManager.WriteHTML(PLResources.Databases_XML_FileName + PLResources.XMLExtention, PLResources.Databases_XSL_FileName, PLResources.Databases_HTM_FileName);
                    backgroundWorker.ReportProgress(10, PLResources.Database_information_Written + Environment.NewLine);
                    
                #endregion

                #region Document Tables & information of each table:- Create Tables & Tabledetail XML file then convert into htm file

                    backgroundWorker.ReportProgress(10, PLResources.Writing_Tables_information + Environment.NewLine);
                    Utility.tables = SQLDBInfoManager.Instance.GetTables(conString);
                    XMLManager.WriteXML(PLResources.Tables_XML_FileName, XMLManager.GetXML(Utility.tables));
                    HTMLManager.WriteHTML(PLResources.Tables_XML_FileName + PLResources.XMLExtention, PLResources.Tables_XSL_FileName, PLResources.Tables_HTM_FileName);

                    foreach (DBDocumenter.BLL.Entities.Table table in Utility.tables)
                    {
                        XMLManager.WriteXML(table.Name, XMLManager.GetXML(table));
                        HTMLManager.WriteHTML(table.Name + PLResources.XMLExtention, PLResources.TableDetails_XSL_FileName, table.Name + PLResources.HTMExtention);
                    }
                    backgroundWorker.ReportProgress(30, PLResources.Tables_information_Written + Environment.NewLine);
                    
                #endregion

                #region Document Stored procedures & information of each procedure:- Create Procedure & Proceduredetail XML file then convert into htm file

                    backgroundWorker.ReportProgress(30, PLResources.Writing_Procedures_information + Environment.NewLine);
                    Utility.storedProcedures = SQLDBInfoManager.Instance.GetStoredProcedures(conString);
                    XMLManager.WriteXML(PLResources.Procedures_XML_FileName, XMLManager.GetXML(Utility.storedProcedures));
                    HTMLManager.WriteHTML(PLResources.Procedures_XML_FileName + PLResources.XMLExtention, PLResources.Procedures_XSL_FileName, PLResources.Procedures_HTM_FileName);
                    
                    foreach (StoredProcedure procedure in Utility.storedProcedures)
                    {
                        XMLManager.WriteXML(procedure.Name, XMLManager.GetXML(procedure));
                        HTMLManager.WriteHTML(procedure.Name + PLResources.XMLExtention, PLResources.ProcedureDetails_XSL_FileName, procedure.Name + PLResources.HTMExtention);
                    }
                    backgroundWorker.ReportProgress(50, PLResources.Procedures_information_Written + Environment.NewLine);

                #endregion

                #region Document Views & information of each view:- Create Views & Viewdetail XML file then convert into htm file

                    backgroundWorker.ReportProgress(50, PLResources.Writing_Views_information + Environment.NewLine);
                    Utility.views = SQLDBInfoManager.Instance.GetViews(conString);
                    XMLManager.WriteXML(PLResources.Views_XML_FileName, XMLManager.GetXML(Utility.views));
                    HTMLManager.WriteHTML(PLResources.Views_XML_FileName + PLResources.XMLExtention, PLResources.Views_XSL_FileName, PLResources.Views_HTM_FileName);

                    foreach (View view in Utility.views)
                    {
                        XMLManager.WriteXML(view.Name, XMLManager.GetXML(view));
                        HTMLManager.WriteHTML(view.Name + PLResources.XMLExtention, PLResources.ViewDetails_XSL_FileName, view.Name + PLResources.HTMExtention);
                    }
                    backgroundWorker.ReportProgress(70, PLResources.Views_information_Written + Environment.NewLine);
                    
                #endregion

                #region Document Functions & information of each function:- Create Functions & Functiondetail XML file then convert into htm file

                    backgroundWorker.ReportProgress(70, PLResources.Writing_Functions_information + Environment.NewLine);
                    Utility.functions = SQLDBInfoManager.Instance.GetFunctions(conString);
                    XMLManager.WriteXML(PLResources.Functions_XML_FileName, XMLManager.GetXML(Utility.functions));
                    HTMLManager.WriteHTML(PLResources.Functions_XML_FileName + PLResources.XMLExtention, PLResources.Functions_XSL_FileName, PLResources.Functions_HTM_FileName);

                    foreach (Function func in Utility.functions)
                    {
                        XMLManager.WriteXML(func.Name, XMLManager.GetXML(func));
                        HTMLManager.WriteHTML(func.Name + PLResources.XMLExtention, PLResources.FunctionDetails_XSL_FileName, func.Name + PLResources.HTMExtention);
                    }
                    backgroundWorker.ReportProgress(90, PLResources.Function_information_Written + Environment.NewLine);
                    
                #endregion
            }
            catch (Exception ex)
            {
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Error, ex.Message);
            }
        }

        /// <summary>
        /// Method is called everytime backgroundWorker.ReportProgress is called which triggers ProgressChanged event.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
        /// <remarks></remarks>
        private void backgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            try
            {
                if (this.SetStatus != null)
                {
                    this.SetStatus(e.UserState.ToString(), e.ProgressPercentage);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Error, ex.Message);
            }
        }

        /// <summary>
        /// Called when DoWork has completed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        /// <remarks></remarks>
        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                UtilityManager.Instance.WriteHTMLHelp();

                if (this.SetStatus != null)
                {
                    this.SetStatus(PLResources.Documentation_is_generated_please_refer_to_Index_file, 100);
                }
                this.Dispatcher.BeginInvoke
                    (
                    System.Windows.Threading.DispatcherPriority.Normal, (System.Threading.ThreadStart)delegate()
                    {
                        this.RaiseEvent(
                            new ShowPopUpEventArgs
                            {
                                RoutedEvent = DBDocumenterEvents.ShowPopUpRoutedEvent,
                                Value = Visibility.Collapsed
                            });
                    });
                UtilityManager.ClearFolder(Folders.HTML);
            }
            catch (Exception ex)
            {
                Logger.WriteLog(LogType.PresentationLayer, LogLevel.Error, ex.Message);
            }
            //SetStatus("Idle...", 100);
        }

        /// <summary>
        /// Handles the Checked event of the chkIntegratedSecurity control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void chkIntegratedSecurity_Checked(object sender, RoutedEventArgs e)
        {
            lblUserName.Opacity = 0.5;
            lblPassword.Opacity = 0.5;

            txtPassword.Opacity = 0.5;
            txtPassword.IsEnabled = false;
            txtUserName.Opacity = 0.5;
            txtUserName.IsEnabled = false;
        }

        /// <summary>
        /// Handles the Unchecked event of the chkIntegratedSecurity control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void chkIntegratedSecurity_Unchecked(object sender, RoutedEventArgs e)
        {
            lblUserName.Opacity = 1;
            lblPassword.Opacity = 1;

            txtPassword.Opacity = 1;
            txtPassword.IsEnabled = true;
            txtUserName.Opacity = 1;
            txtUserName.IsEnabled = true;
        }

        /// <summary>
        /// Handles the SelectionChanged event of the cmbDatabase control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void cmbDatabase_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cmbDatabase.Items.Count > 0)
            {
                Utility.databaseName = cmbDatabase.SelectedItem.ToString();
            }
        }

        /// <summary>
        /// Handles the Expanded event of the folder control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        void folder_Expanded(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = (TreeViewItem)sender;
            if (item.Items.Count == 1 && item.Items[0] == dummyNode)
            {
                item.Items.Clear();
                try
                {
                    foreach (string s in Directory.GetDirectories(item.Tag.ToString()))
                    {
                        TreeViewItem subitem = new TreeViewItem();
                        subitem.Header = s.Substring(s.LastIndexOf("\\") + 1);
                        subitem.Tag = s;
                        subitem.FontWeight = FontWeights.Normal;
                        subitem.Items.Add(dummyNode);
                        subitem.Expanded += new RoutedEventHandler(folder_Expanded);
                        item.Items.Add(subitem);
                    }
                }
                catch (Exception ex)
                {
                    Logger.WriteLog(LogType.PresentationLayer, LogLevel.Warn, ex.Message);
                }
            }
        }

        /// <summary>
        /// Handles the SelectedItemChanged event of the foldersItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedPropertyChangedEventArgs&lt;System.Object&gt;"/> instance containing the event data.</param>
        private void foldersItem_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            TreeView tree = (TreeView)sender;
            TreeViewItem temp = ((TreeViewItem)tree.SelectedItem);

            if (temp == null)
                return;
            SelectedImagePath = string.Empty;
            string temp1 = string.Empty;
            string temp2 = string.Empty;
            while (true)
            {
                temp1 = temp.Header.ToString();
                if (temp1.Contains(@"\"))
                {
                    temp2 = string.Empty;
                }
                SelectedImagePath = temp1 + temp2 + SelectedImagePath;
                if (temp.Parent.GetType().Equals(typeof(TreeView)))
                {
                    break;
                }
                temp = ((TreeViewItem)temp.Parent);
                temp2 = @"\";
            }
            //show user selected path
            Utility.fileLocation = SelectedImagePath;
            //MessageBox.Show(SelectedImagePath);
        }

        #endregion Methods
    }
}